<template>
  <el-row>
    <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
      <div class="canvas-wrapper" ref="canvasWrapper">
      <img :src="frame" class="frame" />
      <img :src="lensModel" class="lens" :style="[style]" />

    </div>
    </el-col>
    <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
      <div class="tool-box">
        <div class="tool-item color-selector">
          <label>设置颜色：</label>
          <el-color-picker class="color" v-model="startColor" @active-change="changeStartColor"></el-color-picker>
          <div class="el-icon-sort extrange" @click="exchangeColor"></div>
          <el-color-picker class="color" v-model="endColor" @active-change="changeEndColor"></el-color-picker>
        </div>
        <div class="tool-item opacity-selector">
          <label>设置透明度：</label>
          <el-slider class="opacity" v-model="opacity" @input="redraw"></el-slider>
        </div>
        
    </div>
    </el-col>
  </el-row>


  
</template>

<script>
import frame from '@/assets/models/frame1.png';
import lensModel from '@/assets/models/glasses1.png'
export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: 'Glasses',
  data(){
    return {
      canvas: null,
      ctx: null,
      frame: frame,
      lensModel: lensModel,
      opacity: 75,
      startColor: '',
      endColor: '',
      lensGroups: [],
      angle: 10,// 顺时针旋转角度
    }
  },
  created(){
    this.canvas = document.createElement('canvas');
    this.initLensPath();
  },
  mounted(){
    

  },
  computed:{
    style(){
      return {
        opacity: this.opacity / 100
      }
    }
  },
  methods:{
    /**
     * 初始化镜片路径
     */
     initLensPath(){
      
      let image = new Image();
      image.src = this.lensModel;
      image.onload = () => {
        let canvas = this.canvas;
        canvas.width = image.width;
        canvas.height = image.height;
        let ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);  
        const data = imageData.data;
        let boundaryPoints = []; 
 
        for(let x = 0; x < canvas.width; x ++){
          for(let y = 0; y < canvas.height; y++){
            if( this.isBoundary(x, y, canvas.width, canvas.height, data)){
              boundaryPoints.push({x,y});
            } 
          }
        }
        this.lensGroups = this.groupAndSort(boundaryPoints);
        let centers = [];
        this.lensGroups.forEach(lens => {
          lens.center = this.center(lens.points);
          centers.push(lens.center);
        });
        
        this.angle = this.rotationAngle(centers[0], centers[1]);

      
        this.redraw();
      }
    },

    /**
     * 获取旋转角度
     */
    rotationAngle(point1, point2){
      // 计算坐标差  
      var dx = point2.x - point1.x;  
      var dy = point2.y - point1.y;  
  
      // 使用Math.atan2计算角度，返回的是弧度值  
      var angleInRadians = Math.atan2(dy, dx);  
  
      // 将弧度转换为度数  
      var angleInDegrees = angleInRadians * (180 / Math.PI);  
    
      // 如果需要，可以将角度值限制在0到360之间  
      if (angleInDegrees < 0) {  
          angleInDegrees += 360;  
      }  
    
      return angleInDegrees;  
    },
    /**
     * 获取中心点坐标
     * @param {*} points 
     */
    center(points){
      const sums = points.reduce((total, point) => {
        total.x += point.x;
        total.y += point.y;
        return total;
      }, {x:0, y:0});

      const center = {
        x: Math.floor(sums.x / points.length),  
        y: Math.floor(sums.y / points.length) 
      }
      return center;
    },
    /**
     * 分组排序
     * @param {*} points 
     */
    groupAndSort(points){
      let lensGroups = [];
      let lensPoints = [];
      let current = null;
      while(points.length > 0){
        if(current == null){
          if(lensPoints.length > 0){
            let lens = {
              points: lensPoints
            }
            lensGroups.push(lens);
            lensPoints = [];
          }
          current = points.splice(0, 1)[0];
          lensPoints.push(current);
        }
        else{
          let closestInfo = this.closestPoint(current, points);
          if(closestInfo.distance < 10){
            current = points.splice(closestInfo.index, 1)[0];
            lensPoints.push(current);
          }
          else{
            current = null;
          }
        }
      }
      if(lensPoints.length > 0){
        let lens = {
          points: lensPoints
        }
        lensGroups.push(lens); 
      }

      return lensGroups;
    },
    /**
     * 获取最近节点下标
     * @param {*} point 
     * @param {*} points 
     */
    closestPoint(point, points){
      let minDistance = 0;
      let index = 0;
      for(let i = 0; i < points.length; i++){
        let item = points[i];
        let distance = Math.sqrt(Math.pow(point.x - item.x, 2) + Math.pow(point.y - item.y, 2));
        if(minDistance == 0 || distance < minDistance){
          minDistance = distance;
          index = i;
        }
         
      }
      return {
        index,
        distance: minDistance,
        point: points[index]
      };
    },

    /**
     * 判断是否边界
     * @param {*} x 
     * @param {*} y 
     * @param {*} width 
     * @param {*} height 
     * @param {*} data 
     */
    isBoundary(x, y, width, height, data){
      let index = (y * width + x) * 4;
      const a = data[index + 3]; // 透明度（alpha）分量，如果不是PNG图片或图片没有透明通道，这个值通常是255 
      if( a > 0){
        let leftIndex = x == 0 ? null : (y * width + (x -1)) * 4;
        let topIndex  = y == 0 ? null : ((y - 1) * width + x) * 4;
        let rightIndex = x == width - 1 ? null : (y * width + (x + 1)) * 4;
        let bottomIndex = y == height - 1 ? null : ((y + 1) * width  + x) * 4;
        let leftAlpha = leftIndex == null ? 0 : data[leftIndex + 3];
        let topAlpha = topIndex == null ? 0 : data[topIndex + 3];
        let rightAlpha = rightIndex == null ? 0 : data[rightIndex + 3];
        let bottomAlpha = bottomIndex == null ? 0 : data[bottomIndex + 3];
        if(leftAlpha * topAlpha * rightAlpha * bottomAlpha == 0){
            
            return true;
        }
      } 
      return false;
    },
    /**
     * 获取矩形坐标
     * @param {*} points 
     */
    getBoundingClientRect(points){
      let minX = Number.MAX_SAFE_INTEGER;
      let maxX = 0;
      let minY = Number.MAX_SAFE_INTEGER;
      let maxY = 0;
      points.forEach(point => {
        
        minX = Math.min(minX, point.x);
        maxX = Math.max(maxX, point.x);
        minY = Math.min(minY, point.y);
        maxY = Math.max(maxY, point.y);

      });
      return {
        x1: minX,
        y1: minY,
        x2: maxX,
        y2: maxY
      }
    },
    /**
     * 改变起始颜色
     * @param {*} e 
     */
    changeStartColor(e){
      this.startColor = e;
      this.redraw();
    },
    /**
     * 改变结束颜色
     * @param {*} e 
     */
    changeEndColor(e){
      this.endColor = e;
      this.redraw();
    },
    /**
     * 切换颜色
     */
    exchangeColor(){
      console.log(this.endColor);
      let tmpColor = this.startColor;
      this.startColor = this.endColor;
      this.endColor = tmpColor;
      
      this.redraw();
    },
    /**
     * 重绘
     */
    redraw(){
      if(this.startColor || this.endColor){
        let startColor = this.startColor || this.endColor;
        let endColor = this.endColor || this.startColor;
        let canvas = this.canvas;
        let ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
          this.lensGroups.forEach(lens => {
            this.drawLens(canvas, lens, startColor, endColor);
          })
          
          this.lensModel = canvas.toDataURL("image/png");
      }

      
    },

    /**
     * 绘制镜片
     * @param {*} canvas 
     * @param {*} lens 
     */
     drawLens(canvas, lens, startColor, endColor){
        let points = lens.points;
        let ctx = canvas.getContext('2d');
        // 使用Path2D创建路径  
        const path = new Path2D();  
        path.moveTo(points[0].x, points[0].y);  
        points.slice(1).forEach(point => path.lineTo(point.x, point.y));  
        path.closePath(); // 闭合路径，确保填充是完整的 
        
        let rect = this.getBoundingClientRect(points);

        const radians = this.angle * 2 * Math.PI / 360;
        const offsetX = Math.sin(radians) * (rect.x2 - rect.x1);
        const offsetY = Math.tan(radians) * offsetX;
        

       
        const startX = rect.x1;
        const startY = rect.y1;
        const endX = rect.x1 - offsetX;
        const endY = rect.y2 - offsetY;
        

          
        // 创建线性渐变  
        const gradient = ctx.createLinearGradient(startX, startY, endX, endY);  
        gradient.addColorStop(0, startColor); // 渐变的开始颜色  
        gradient.addColorStop(1, endColor); // 渐变的结束颜色  
          
        // 设置填充样式为渐变  
        ctx.fillStyle = gradient;  
          
        // 填充路径  
        ctx.fill(path); 
        //ctx.fillRect(rect.x1, rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1); 
        
        //ctx.fillStyle = 'red';
        //ctx.fillRect(lens.center.x - 1, lens.center.y - 1, 3, 3);
        
        // 如果你还想描边路径，可以这样做：  
        //ctx.strokeStyle = gradient; // 设置描边颜色  
        //ctx.lineWidth = 4; // 设置描边宽度  
        //ctx.stroke(path); // 描边路径
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>


 .canvas-wrapper{
  background-image: radial-gradient(circle at 48.7% 44.3%, rgb(255, 255, 255) 0%, rgb(255, 255, 255) 22.9%, rgb(220, 220, 220) 76.7%, rgb(200, 200, 200) 100.2%);
  position:relative;
 }
 .frame{
  width: 100%;
 }
 .lens{
  position: absolute;
  top:0;
  left:0;
  width: 100%;
  z-index:10;
  opacity: 1;
 }

 .tool-box{
  box-sizing: border-box;
  padding:30px;
  
  .color-selector{
    width: 250px;
    display: flex;
    justify-content: space-between;
    line-height: 40px;
  }

 }

 .tool-item{
  margin-bottom: 20px;
 }

 .opacity-selector{
    flex:1;
  }

 .extrange{
  width: 40px;
  height: 40px;
  display: inline-block;
  text-align: center;
  line-height: 40px;
  vertical-align: middle;
  transform: rotate(90deg);
  cursor: pointer;
  font-weight: bold;
 }



</style>
